<?php
/**
 * Created by PhpStorm.
 * User: 85210755@qq.com
 * NickName: 柏宇娜
 * Date: 2018/3/10 10:01
 */

namespace Payment;

use Payment\Ali\Aop\request\AlipayTradeFastpayRefundQueryRequest;
use Payment\Ali\Service\AlipayTradeService;
use Payment\Ali\Aop\request\AlipayTradeAppPayRequest;
use Payment\Ali\Buildermodel\AlipayTradeWapPayContentBuilder;
use Payment\Ali\Buildermodel\AlipayTradePagePayContentBuilder;
use Payment\Ali\Buildermodel\AlipayTradeQueryContentBuilder;
use Payment\Ali\Buildermodel\AlipayTradeRefundContentBuilder;
use Payment\Ali\Buildermodel\AlipayTradeFastpayRefundQueryContentBuilder;
use Payment\Ali\Buildermodel\AlipayTradeFundTransToaccountContentBuilder;
use Payment\Ali\Buildermodel\AlipayTradePrecreateContentBuilder;

class AliPay
{
    private $config = [
        'app_id'               => "",
        //商户私钥，您的原始格式RSA私钥
        'merchant_private_key' => "",
        //异步通知地址
        'notify_url'           => "",
        //同步跳转
        'return_url'           => "",
        //编码格式
        'charset'              => "UTF-8",
        //签名方式
        'sign_type'            => "RSA2",
        //支付宝网关
        'gatewayUrl'           => "https://openapi.alipay.com/gateway.do",
        //支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        'alipay_public_key'    => "",
        //最大查询重试次数
        'MaxQueryRetry'        => "10",
        //查询间隔
        'QueryDuration'        => "3"
    ];

    public function __construct(array $config = [])
    {
        $this->config = array_merge($this->config, $config);
    }

    public function app($payData)
    {
        $order   = [
            'subject'      => $payData['subject'],
            'out_trade_no' => $payData['out_trade_no'],
            'total_amount' => $payData['total_fee'],
            'product_code' => 'QUICK_MSECURITY_PAY'
        ];
        $builder = new AlipayTradeAppPayRequest();
        if (isset($payData['notify_url'])) {
            $notify_url = $payData['notify_url'];
        } else {
            $notify_url = $this->config['notify_url'];
        }
        $builder->setNotifyUrl($notify_url);
        $builder->setBizContent(json_encode($order));
        $service  = new AlipayTradeService($this->config);
        $response = $service->app($builder, $notify_url);
        return $response;
    }

    /**
     * 手机H5支付
     * @param $wxConfig
     * @param $payData
     */
    public function h5Pay($payData)
    {
        $builder = new AlipayTradeWapPayContentBuilder();
        $builder->setBody($payData['body']);
        $builder->setSubject($payData['subject']);
        $builder->setOutTradeNo($payData['out_trade_no']);
        $builder->setTotalAmount($payData['total_fee']);
        //$builder->setTimeExpress($timeout_express);
        $pay = new AlipayTradeService($this->config);
        $pay->wapPay($builder, $payData['return_url'], $payData['notify_url']);
    }

    /**
     * 电脑网页支付
     * @param $subject
     * @param $out_trade_no
     * @param $total_fee
     * @param $return_url
     * @param $notify_url
     * @param string $goods_tag
     * @param string $attach
     */
    public function webPay($payData)
    {
        $builder = new AlipayTradePagePayContentBuilder();
        $builder->setBody($payData['subject']);
        $builder->setSubject($payData['subject']);
        $builder->setTotalAmount($payData['total_fee']);
        $builder->setOutTradeNo($payData['out_trade_no']);
        $pay = new AlipayTradeService($this->config);
        $pay->pagePay($builder, $payData['return_url'], $payData['notify_url']);//跳转
    }

    public function qrPay($payData)
    {
        $builder = new AlipayTradePrecreateContentBuilder();
        $builder->setOutTradeNo($payData['out_trade_no']);
        $builder->setTotalAmount($payData['total_fee']);
        $builder->setTimeExpress($payData['time_express'] ?? '120m');
        $builder->setSubject($payData['subject']);
        $builder->setNotifyUrl($payData['notify_url']);
        $builder->setDisablePayChinnels('pcredit,pcreditpayInstallment,creditCard,creditCardExpress,creditCardCartoon');
        $qrPay  = new AlipayTradeService($this->config);
        $result = $qrPay->qrPay($builder);
        $res    = $result->getResponse();
        if ($result->getTradeStatus() !== 'SUCCESS')
            return ['ret' => 1, 'msg' => $res];

        return ['ret' => 0, 'result' => 'http://qr.zy52.cn?data=' . urlencode($res->qr_code)];
    }

    /**
     * 单笔转账到支付宝账户
     * @param $payData
     * @return array
     */
    public function transToAccount($payData)
    {
        $type    = [0 => 'ALIPAY_USERID', 1 => 'ALIPAY_LOGONID'];
        $builder = new AlipayTradeFundTransToaccountContentBuilder();
        $builder->setOutBizNo($payData['out_biz_no']);
        $builder->setPayeeType($type[$payData['payee_type']]);
        $builder->setPayeeAccount($payData['payee_account']);
        $builder->setAmount($payData['amount']);
        if ($payData['payer_show_name']) $builder->setPayerShowName($payData['payer_show_name']);
        if ($payData['payee_real_name']) $builder->setPayeeRealName($payData['payee_real_name']);
        if ($payData['remark']) $builder->setRemark($payData['remark']);
        $pay    = new AlipayTradeService($this->config);
        $result = $pay->transfer($builder);
        $res    = $result->alipay_fund_trans_toaccount_transfer_response;
        if ($res->code != 10000)
            return ['ret' => 2, 'msg' => $res->sub_msg];
        return ['ret' => 0, 'result' => json_decode(json_encode($res), true)];
    }

    /**
     * 退款
     * @param $data
     * @return array|mixed
     */
    public function refund($data)
    {
        $builder = new AlipayTradeRefundContentBuilder();
        if ($data['out_trade_no']) {
            $builder->setOutTradeNo($data['out_trade_no']);
        } elseif ($data['trade_no']) {
            $builder->setOutTradeNo($data['trade_no']);
        } else {
            return ['ret' => 1, 'msg' => '订单号与微信交易号不能同时为空'];
        }
        $builder->setRefundAmount($data['refund_fee']);
        $builder->setOutRequestNo($data['refund_no']);
        $aop    = new AlipayTradeService($this->config);
        $result = $aop->Refund($builder);
        if (!isset($result->code))
            return ['ret' => 2, 'msg' => '退款申请失败'];
        if ($result->code != '10000')
            return ['ret' => 3, 'msg' => $result->msg . $result->sub_msg];
        return json_decode(json_encode($result), true);
    }

    /**
     * 交易订单查询
     * @param string $out_trade_no
     * @param string $trade_no 商户订单号、支付宝交易号 参数二选一
     * @return array|mixed
     */
    public function query($out_trade_no = '', $trade_no = '')
    {
        $builder = new AlipayTradeQueryContentBuilder();
        if ($out_trade_no) {
            $builder->setOutTradeNo($out_trade_no);
        } elseif ($trade_no) {
            $builder->setTradeNo($trade_no);
        } else {
            return ['ret' => 1, 'msg' => '订单号与微信交易号不能同时为空'];
        }
        $aop    = new AlipayTradeService($this->config);
        $result = $aop->Query($builder);
        if (!isset($result->code))
            return ['ret' => 2, 'msg' => '查询失败'];
        if ($result->code != '10000')
            return ['ret' => 2, 'msg' => $result->sub_msg];
        return json_decode(json_encode($result), true);
    }

    /**
     * 退款查询
     * @param $data
     * @return array
     */
    public function refundQuery($data)
    {
        $builder = new AlipayTradeFastpayRefundQueryContentBuilder();
        if ($data['out_trade_no']) {
            $builder->setOutTradeNo($data['out_trade_no']);
        } elseif ($data['trade_no']) {
            $builder->setOutTradeNo($data['trade_no']);
        } else {
            return ['ret' => 1, 'msg' => '订单号与支付宝交易号不能同时为空'];
        }
        if ($data['out_refund_no']) {
            $builder->setOutRequestNo($data['out_refund_no']);
        } elseif ($data['refund_no']) {
            $builder->setOutRequestNo($data['refund_no']);
        } else {
            return ['ret' => 1, 'msg' => '退款单号与支付宝退款交易号不能同时为空'];
        }
        $aop    = new AlipayTradeService($this->config);
        $result = $aop->refundQuery($builder);
        if (!isset($result->alipay_trade_fastpay_refund_query_response->code))
            return ['ret' => 2, 'msg' => '查询失败'];
        $result = $result->alipay_trade_fastpay_refund_query_response;
        if ($result->code != '10000')
            return ['ret' => 3, 'msg' => $result->msg . $result->sub_msg];
        return ['ret' => 0, 'msg' => json_decode(json_encode($result), true)];
    }

    public function notify($func)
    {
        if (empty($_POST)) {
            exit('fail');
        }

        $service = new AlipayTradeService($this->config);
        $result  = $service->check($_POST);
        if ($result) {
            if ($_POST['trade_status'] == 'TRADE_SUCCESS' || $_POST['trade_status'] == 'TRADE_FINISHED') {
                $param = [
                    'out_trade_no'   => $_POST['out_trade_no'],
                    'transaction_id' => $_POST['trade_no'],
                    'total_amount'   => $_POST['total_amount'],
                    'pay_code'       => strtolower(__CLASS__),
                    'pay_name'       => '支付宝',
                ];
                $res   = call_user_func($func, $param);
                if (true === $res)
                    exit('success');
            }
        }
        exit('fail');
    }

    /**
     * 支持同步跳转页面 参数验签
     * @param $input
     * @return bool
     */
    public function checkSign($input)
    {
        $service = new AlipayTradeService($this->config);
        return $service->check($input);
    }
}